package br.com.afi.encoding_converter.console.interpreter;

import java.util.HashMap;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import br.com.afi.encoding_converter.Command;
import br.com.afi.pattern.interpreter.StackEvaluator;
import br.com.afi.pattern.interpreter.expression.Expression;
import br.com.afi.pattern.interpreter.expression.StringExpression;

/**
 * Classe responsável por interpretar as entradas do console.
 * 
 * @author André de Fontana Ignacio
 * @version 1.0
 */
public class ConsoleEvaluator extends StackEvaluator
{
	/**
	 * Cria o objeto atribuindo a string que será interpretada.
	 * 
	 * @param args Entrada através do console
	 */
	public ConsoleEvaluator( String[] args )
	{
		final Pattern simpleCommandPattern = Pattern.compile( SimpleCommandExpression.REGEX );
		final Pattern complexCommandPattern = Pattern.compile( ComplexCommandExpression.REGEX );
		final Stack<Expression> expressionStack = new Stack<Expression>();
		final Command command = new Command();
		
		//For no sentido inverso
		for(int i = ( args.length - 1 ); i >= 0 ; i--)
		{
			final String m = args[i];
			final Matcher simpleCommandMatcher = simpleCommandPattern.matcher( m );
			final Matcher complexCommandMatcher = complexCommandPattern.matcher( m );
			
			final boolean complexCommand = complexCommandMatcher.find();
			final boolean simpleCommand = !complexCommand && simpleCommandMatcher.find();
			
			if( complexCommand )
			{
				final String str = m.substring(1);
				final Expression expression = new ComplexCommandExpression( str, expressionStack.pop(), command );
				expressionStack.push( expression );
			}
			else if( simpleCommand )
			{
				final String str = m.substring(1);
				final Expression expression = new SimpleCommandExpression( str, command );
				expressionStack.push( expression );
			}
			else
			{
				expressionStack.push( new StringExpression( m ) );
			}
		}
		setExpressionStack( expressionStack );
	}
	/**
	 * Interpreta.
	 * 
	 * @return Resultado
	 */
	public Command evaluate()
	{
		return (Command) evaluate( new HashMap<String, Object>() );
	}
}
